package monitor

import (
	"gitee.com/amoyx/cloud-provider/pkg/cloud/tencent/models"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	mo "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/monitor/v20180724"
	"strings"
)

type PrometheusGreeter interface {
	Prometheus(region string) PrometheusInterface
}

type PrometheusInterface interface {
	Get(id string) (result models.PrometheusResponse, err error)
	ListByName(name string) (list []models.PrometheusResponse, err error)
	ListByStatus(status int64) (list []models.PrometheusResponse, err error)
	ListAll() (list []models.PrometheusResponse, err error)
	CreateInstance(args models.PrometheusRequest) (result models.CreateResponseParams, err error)
	ModifyInstance(id string, name string, dataRetentionTime int64) (err error)
	BindGrafanaInstance(id string, grafanaId string) (err error)
	UnBindGrafanaInstance(id string, grafanaId string) (err error)
	DestroyInstance(id string) (err error)
	DeleteInstance(id string) (err error)
}

type prometheus struct {
	m      *Monitor
	region string
	client *mo.Client
}

func newPrometheus(monitor *Monitor, region string) PrometheusInterface {
	v := &prometheus{
		m:      monitor,
		region: region,
	}
	cpf := profile.NewClientProfile()
	cpf.HttpProfile.Endpoint = string(MonitorEndPoint)
	client, _ := mo.NewClient(v.m.Credential(), v.region, cpf)
	v.client = client
	return v
}

func (p *prometheus) CreateInstance(args models.PrometheusRequest) (result models.CreateResponseParams, err error) {
	request := mo.NewCreatePrometheusMultiTenantInstancePostPayModeRequest()
	request.InstanceName = common.StringPtr(args.InstanceName)
	request.VpcId = common.StringPtr(args.VpcId)
	request.SubnetId = common.StringPtr(args.SubnetId)
	if args.DataRetentionTime < 15 || args.DataRetentionTime > 180 {
		args.DataRetentionTime = 30
	}
	request.DataRetentionTime = common.Int64Ptr(args.DataRetentionTime)
	request.Zone = common.StringPtr(args.Zone)
	if strings.TrimSpace(args.GrafanaInstanceId) != "" {
		request.GrafanaInstanceId = common.StringPtr(args.GrafanaInstanceId)
	}
	response, err := p.client.CreatePrometheusMultiTenantInstancePostPayMode(request)
	if err != nil {
		return
	}
	res := response.Response
	result.RequestId = *res.RequestId
	result.InstanceSet = append(result.InstanceSet, *res.InstanceId)
	return
}

// ModifyInstance 修改实例配置
func (p *prometheus) ModifyInstance(id string, name string, dataRetentionTime int64) (err error) {
	request := mo.NewModifyPrometheusInstanceAttributesRequest()
	if strings.TrimSpace(name) != "" {
		request.InstanceName = common.StringPtr(name)
	}
	request.InstanceId = common.StringPtr(id)

	if dataRetentionTime >= 15 && dataRetentionTime <= 180 {
		request.DataRetentionTime = common.Int64Ptr(dataRetentionTime)
	}
	_, err = p.client.ModifyPrometheusInstanceAttributes(request)
	return
}

// BindGrafanaInstance 绑定grafana实例
func (p *prometheus) BindGrafanaInstance(id string, grafanaId string) (err error) {
	request := mo.NewBindPrometheusManagedGrafanaRequest()
	request.InstanceId = common.StringPtr(id)
	request.GrafanaId = common.StringPtr(grafanaId)
	_, err = p.client.BindPrometheusManagedGrafana(request)
	return
}

// UnBindGrafanaInstance 解除绑定grafana实例
func (p *prometheus) UnBindGrafanaInstance(id string, grafanaId string) (err error) {
	request := mo.NewUnbindPrometheusManagedGrafanaRequest()
	request.InstanceId = common.StringPtr(id)
	request.GrafanaId = common.StringPtr(grafanaId)
	_, err = p.client.UnbindPrometheusManagedGrafana(request)
	return
}

// DestroyInstance 销毁/退还 prometheus实例
func (p *prometheus) DestroyInstance(id string) (err error) {
	request := mo.NewTerminatePrometheusInstancesRequest()
	request.InstanceIds = common.StringPtrs([]string{id})
	_, err = p.client.TerminatePrometheusInstances(request)
	return
}

// DeleteInstance  释放/删除 prometheus实例， 释放/删除实例之前，需要先销毁/退还
func (p *prometheus) DeleteInstance(id string) (err error) {
	request := mo.NewDestroyPrometheusInstanceRequest()
	request.InstanceId = common.StringPtr(id)
	_, err = p.client.DestroyPrometheusInstance(request)
	return
}

func (p *prometheus) Get(id string) (result models.PrometheusResponse, err error) {
	list, err := p.query(id, "", 0)
	if len(list) > 0 {
		result = list[0]
	}
	return
}

func (p *prometheus) ListByStatus(status int64) (list []models.PrometheusResponse, err error) {
	return p.query("", "", status)
}

func (p *prometheus) ListByName(name string) (list []models.PrometheusResponse, err error) {
	return p.query("", name, 0)
}

func (p *prometheus) ListAll() (list []models.PrometheusResponse, err error) {
	return p.query("", "", 0)
}

func (p *prometheus) query(id string, name string, status int64) (list []models.PrometheusResponse, err error) {
	request := mo.NewDescribePrometheusInstancesRequest()
	if strings.TrimSpace(id) != "" {
		request.InstanceIds = common.StringPtrs([]string{id})
	}
	if strings.TrimSpace(name) != "" {
		request.InstanceName = common.StringPtr(name)
	}
	if status > 0 {
		request.InstanceStatus = common.Int64Ptrs([]int64{status})
	}
	request.Limit = common.Int64Ptr(100)
	request.Offset = common.Int64Ptr(0)
	response, err := p.client.DescribePrometheusInstances(request)
	if err != nil {
		return
	}
	for _, row := range response.Response.InstanceSet {
		list = append(list, models.PrometheusResponse{
			InstanceId:         *row.InstanceId,
			InstanceName:       *row.InstanceName,
			InstanceChargeType: *row.InstanceChargeType,
			RegionId:           *row.RegionId,
			Zone:               *row.Zone,
			VpcId:              *row.VpcId,
			SubnetId:           *row.SubnetId,
			DataRetentionTime:  *row.DataRetentionTime,
			InstanceStatus:     *row.InstanceStatus,
			GrafanaURL:         *row.GrafanaURL,
			CreatedAt:          *row.CreatedAt,
			EnableGrafana:      *row.EnableGrafana,
			IPv4Address:        *row.IPv4Address,
			ExpireTime:         *row.ExpireTime,
			ChargeStatus:       *row.ChargeStatus,
			SpecName:           *row.SpecName,
			AutoRenewFlag:      *row.AutoRenewFlag,
			IsNearExpire:       *row.IsNearExpire,
			AuthToken:          *row.AuthToken,
			RemoteWrite:        *row.RemoteWrite,
			ApiRootPath:        *row.ApiRootPath,
			ProxyAddress:       *row.ProxyAddress,
			GrafanaInstanceId:  *row.GrafanaInstanceId,
			AlertRuleLimit:     *row.AlertRuleLimit,
			RecordingRuleLimit: *row.RecordingRuleLimit,
			MigrationType:      *row.MigrationType,
		})
	}
	return
}
